<!DOCTYPE html>
<html>
<head>
	<title>递归和预编译--学习-上</title>
	<meta charset="utf-8">
</head>
<body>

</body>
<script type="text/javascript">

	/***
	* 递归的规则
	* 1. 具有相同的规则
	* 2. 具有终止递归循环的已知条件
	*
	****/
	/**
	*	递归的好处 代码简洁
	**/
	/**
	*	递归的坏处  效率低，执行耗时 ，时空复杂度高
	**/
	/***
	*  先执行的方法，最后被执行完成
	**/
	/**
	* 递归求解 一个正数的阶乘
	**/
	/*
	function mul(n) {
		//判断循环条件
		if(n>1){
			return n * mul(n-1)
		}
		return 1;
	}
	console.log(mul(5))
	*/
	/**
	*  js 是单线程的解释性语言
	*  js 执行顺序 1. 语法分析  2. 预编译 3. 解释执行
	*	1. 语法分析，通篇扫描整个代码，查看是否存在低级错误
	*	    not defined 未定义的--未声明  程序终止执行、
	*		undefined 已声明变量，但未赋值 程序可继续执行
	*
	*		针对es5
	*    	函数声明存在整体提升
	*		变量 的存在声明的提升  es6 存在 Cannot access 'a' before initialization 报错 在初始化之前使用
	**/
	
	// console.log(a);
	// var a = 1;
	// console.log(window)


	// function windwowFun(){
		// var a = b = 123;
	// }
	// windwowFun();



	/**
	*  预编译发生在 函数执行之前
	**/

	/**
	function fn (a){
		console.log(a);

		var a = 1;
		console.log(a)

		function a(){}
		console.log(a)

		console.log(b);
		var b = function (){}
		console.log(b)

		function d(  ){}

	}
	fn(1);
	**/
	/**
	* 预编译过程
	* 1. 创建AO对象（Activation Object） 执行期上下文   个人认为是 函数体内部的全局控制
	* 2. 找形参和变量声明，将变量和形参名作为AO对象属性名，值为undefined
	* 3. 实参值和形参统一
	* 4. 在函数体内部找函数声明，值赋予函数体	
	**/
	/**
	*以fn函数为例
	* 预编译
	* 1. AO:{}
	* 2. AO:{a:undefined,b:undefined}
	* 3. AO:{a:1,b:undefined}
	* 4. AO:{a:function a(){},b:undefined,d:function(){}}
	* 开始输出语句执行时的值
	* 第一处: AO:{a:function a(){},b:undefined,d:function(){}}  输出 function a(){}
	* 第二处: AO:{a:1,b:undefined,d:function(){}}  输出1  ；====> 重新赋值了
	* 第三处: AO:{a:1,b:undefined,d:function(){}}  输出1   ；===>未发生重新赋值
	* 第四处: AO:{a:1,b:undefined,d:function(){}}  输出undefined   ；===>未发生重新赋值
	* 第五处: AO:{a:1,b:function(){},d:function(){}}  输出function(){}   ；===> b重新赋值
	**/ 
	/***
	if(true){
		function c(){
			console.log(c);// function c(){...}
		}

		c();    
	}***/
	/**
	(window.foo)||(window.foo = 'bar')
	console.log(window.foo)
	**/
</script>
</html>